/**
 ******************************************************************************
 * @file    Project/STM32F10x_StdPeriph_Template/main.c
 * @author  MCD Application Team
 * @version V3.6.0
 * @date    20-September-2021
 * @brief   Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2011 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Standard includes. */
#include <stdio.h>

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"

/* Library includes. */
#include "stm32f10x_it.h"

/* User includes. */
#include "systick.h"
#include "usart.h"

/** @addtogroup STM32F10x_StdPeriph_Template
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static TaskHandle_t xStartTaskHandler;
static TaskHandle_t xLEDTaskHandler;
static TaskHandle_t xPrintTaskHandler;
StackType_t puxLEDTask_StackBuffer[32];
StackType_t puxPrintTask_StackBuffer[64];
StaticTask_t pxTCBOfLEDTask;
StaticTask_t pxTCBOfPrintTask;
/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) {
    printf("--- Stack Overflow in Task: %s\r\n", pcTaskName);
    while (1); // 死循环或系统复位
}

static void LED_Init(){
    GPIO_InitTypeDef GPIO_InitStructure = {
        .GPIO_Pin = GPIO_Pin_13,
        .GPIO_Mode = GPIO_Mode_Out_PP,
        .GPIO_Speed = GPIO_Speed_50MHz,
    };
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
}

static void LEDTask(void* pvParameters){
    while(1){
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
        vTaskDelay(1000);
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
        vTaskDelay(1000);
    }
}

static void PrintTask(void* pvParameters){
    while(1){
        vTaskDelay(1000);
        printf("- STM32F103C8T6 Working!\r\n");
        vTaskDelay(1000);
        printf("- Using StdPeriph!\r\n");
    }
}

/* 初始化任务 */
static void StartTask(void* pvParameters) {
    USART1_Init();
    LED_Init();
    // led_init();
    // buzzer_init();
    // hc_sr04_init();

    printf("- StartTask\r\n");

    taskENTER_CRITICAL();

    xLEDTaskHandler = xTaskCreateStatic(LEDTask, "LED Task", 32, NULL, 2, puxLEDTask_StackBuffer, &pxTCBOfLEDTask);
    if(xLEDTaskHandler == NULL){
        printf("- Create TaskLED1 Failed!\r\n");
    }
    xPrintTaskHandler = xTaskCreateStatic(PrintTask, "Print Task", 64, NULL, 2, puxPrintTask_StackBuffer, &pxTCBOfPrintTask);
    if(xPrintTaskHandler == NULL){
        printf("- Create PrintTask Failed!\r\n");
    }

    #if LED_CHASER
    xTaskLED1Handler = xTaskCreateStatic(LED1Task, "TaskLED1", 32, NULL, 3, puxLED1Task_StackBuffer, &pxTCBOfLED1Task);
    xTaskLED2Handler = xTaskCreateStatic(LED2Task, "TaskLED2", 32, NULL, 2, puxLED2Task_StackBuffer, &pxTCBOfLED2Task);
    xTaskLED3Handler = xTaskCreateStatic(LED3Task, "TaskLED3", 32, NULL, 1, puxLED3Task_StackBuffer, &pxTCBOfLED3Task);
    // 首次执行先发送任务通知给LED1任务
    xTaskNotifyGive(xTaskLED1Handler);
    #endif

    #if CARBACKING_RADAR
    xTaskCreateStatic(
        fGetDisTask, "Get distance task", 128, (void*)&g_pfDistance, 2, puxGetDistanceTask_StackBuffer, &pxTCBOfGetDistanceTask);
    xTaskCreateStatic(
        vBeepTask, "Beep task", 128, (void*)&g_pfDistance, 2, puxBeepTask_StackBuffer, &pxTCBOfBeepTask);
    #endif

    vTaskDelete(xStartTaskHandler);

    taskEXIT_CRITICAL();
}


/**
 * @brief  Main program.
 * @param  None
 * @retval None
 */
int main(void) {
    /*!< At this stage the microcontroller clock setting is already configured,
         this is done through SystemInit() function which is called from startup
         file (startup_stm32f10x_xx.s) before to branch to application main.
         To reconfigure the default setting of SystemInit() function, refer to
         system_stm32f10x.c file
       */
    /* Add your application code here */
    
    // 设置中断优先级分组为4位抢占优先级，0位响应优先级
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    
    // 创建初始化任务
    xTaskCreate(StartTask, "Start task", 128, NULL, 1, &xStartTaskHandler);  

    // 启动调度器
    vTaskStartScheduler();

    /*!We should never get here as control is now taken by the scheduler. */

    /* Infinite loop */
    while (1) {
        
    }
}



#ifdef USE_FULL_ASSERT

/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line) {
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1) {
    }
}
#endif

/**
 * @}
 */
